#include "Global.h"

namespace Object
{
	Base::~Base()
	{
		for (auto& [ty, map] : _cld)
		{
			for (auto& [id, pObj] : map)
			{
				delete pObj;
			}
		}

		_cld.clear();
	}

	std::ostream& Base::fillOs(std::ostream& os) const
	{
		fillSelfOs(os);
		if (_cld.empty())
			return os;

		return fillChildenOs(os);;
	}


	std::ostream& Base::fillSelfOs(std::ostream& os) const
	{
		return os << "[" << _ty.name() << "_" << _id << "]";
	}

	std::ostream& Base::fillChildenOs(std::ostream& os) const
	{
		using CompData = Component::FillOs::Data;
		auto pCld = getCld<CompData>();
		if (!pCld)
			return os;

		if (pCld->empty())
			return os;

		os << "={";
		bool first = true;
		for (auto [id, pObj] : *pCld)
		{
			if (first) first = false;
			else os << ",";

			auto pData = dynamic_cast<const CompData*>(pObj);
			if (!pData)
			{
				os << "[" << id << "]=<NullCompData>";
				continue;
			}

			for (auto& [order, pr] : pData->_orderMap)
			{
				auto pObj = get(pr.first, pr.second);
				if (pObj)
					pObj->fillOs(os);
				else
					os << "[" << pr.first.name() << "_" << pr.second << "]=<NullObj>";
			}
		}

		os << "}";
		return os;
	}

	auto Base::get(std::type_index ty, size_t id) const->const Base*
	{
		auto cldIt = _cld.find(ty);
		if (cldIt == _cld.end())
			return nullptr;

		auto objIt = cldIt->second.find(id);
		if (objIt == cldIt->second.end())
			return nullptr;

		return objIt->second;
	}

	auto Base::initCallback()->bool
	{
		if (!init())
			return false;

		initComponent<Component::FillOs::Define, Component::FillOs::Data>();
		return true;
	}

	namespace Component
	{
		namespace FillOs
		{
			Define::Define(uint8_t format, char separator, size_t order) : Base(order)
			{
				_format = format;
				_separator = separator;
			}
		}
	}
}